package test.util;

import java.io.File;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.entity.mime.HttpMultipartMode;
import org.apache.http.entity.mime.MultipartEntityBuilder;
import org.apache.http.entity.mime.content.FileBody;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.CharsetUtils;
import org.apache.http.util.EntityUtils;

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ObjectNode;
/**
 * 模拟浏览器访问接口，用于测试接口
 * @author chenchengjin
 * @Date 2016/01/13 create
 */
public class HttpConnUtils {
	
	private static HttpClient httpClient;
	
	//登录接口
//	private static final String LOGIN_URL = "http://127.0.0.1:8080/suneee-cloud/api-userLogin.login";
	private static final String LOGIN_URL = "http://127.0.0.1:8088/suneee-cloud/api-userLogin.loginEn";
	//账号
//	private static final String ACCOUNT = "admin";
	private static final String ACCOUNT = "shangwen";
	//密码
//	private static final String PSW = "123456";
	private static final String PSW = "123";
	//参数以普通方式提交（直接在url后面加?参数名=...）
	public static final String TYPE_NORMAL = "normal";
	//参数以object的方式提交（key/value）
	public static final String TYPE_JSON = "json";
	
	/**
	 * 创建浏览器对象，即模拟打开浏览器
	 * @author chenchengjin
	 * @Date 2016/01/13 create
	 * @return HttpClient
	 */
	private static HttpClient getClient(){
		if(httpClient == null){
			httpClient = HttpClients.createDefault();
		}
		return httpClient;
	}
	
	/**
	 * 模拟浏览器登录
	 * @param url 登录接口
	 * @param userName 用户名
	 * @param psw 密码
	 * @return String 登录成功返回服务器消息，失败则返回空
	 * @throws Exception
	 */
	private static String login(String url,String userName,String psw) throws Exception{
		//1 得到浏览器
		HttpClient client = HttpConnUtils.getClient();
		StringBuffer sbf = new StringBuffer();
		sbf.append(url).append("?account=").append(userName).append("&password=").append(psw);
		
		sbf.append("&enterpriseName=111&clientIp=&appCode=");
		
		//2 指定请求方式
		HttpGet get = new HttpGet(sbf.toString());
		//3执行请求
		HttpResponse response = client.execute(get);
		//4判断请求是否成功
		int statusCode = response.getStatusLine().getStatusCode();
		if(statusCode == 200){
			return response.toString();
		}
		return null;
	}
	
	/**
	 * 模拟浏览器访问接口
	 * @param url 接口地址
	 * @param params 把参数直接封装到Map对象里面，key为参数名，value为参数值
	 * @param type 为TYPE_NORMAL时，访问接口方式为url加参数；为TYPE_JSON时，把参数封装成json对象提交
	 * @return String 服务器返回的字符串
	 * @throws Exception
	 */
	public static String requestInterface(String url,Map<String,Object> params,String type) throws Exception{
		//先登录
		String loginResponse = HttpConnUtils.login(LOGIN_URL, ACCOUNT, PSW);
		if(loginResponse == null){
			throw new Exception("登录失败！");
		}
		StringBuffer sbf = new StringBuffer();
		sbf.append(url);
		if(TYPE_NORMAL.equals(type)){
			if(params != null && !params.isEmpty()){
				sbf.append("?");
				List<String> keySet = new ArrayList<>(params.keySet());
				for(int i = 0;i < keySet.size();i++){
					sbf.append(keySet.get(i)).append("=");
					sbf.append(params.get(keySet.get(i)));
					if(i != keySet.size() - 1){
						sbf.append("&");
					}
				}
			}
		}
		
		HttpPost post = new HttpPost(sbf.toString());
		String entityStr = null;
		if(TYPE_JSON.equals(type)){
			if(params != null && !params.isEmpty()){
				ObjectMapper mapper = new ObjectMapper();
				ObjectNode node = mapper.createObjectNode();
				mapToNode(params,node);
				entityStr = mapper.writeValueAsString(node);
				System.out.println("--------------" + entityStr);
			}
		}
		if(entityStr != null && !"".equals(entityStr)){
			StringEntity strEntity = new StringEntity(entityStr, "utf-8");
			strEntity.setContentEncoding("UTF-8");
			strEntity.setContentType("application/json");
			post.setEntity(strEntity);
		}
		HttpResponse response = HttpConnUtils.getClient().execute(post);
		String resData = EntityUtils.toString(response.getEntity());
		return resData;
	}
	
	private static ObjectNode mapToNode(Map<String,Object> params,ObjectNode node) throws Exception{
		List<String> keySet = new ArrayList<>(params.keySet());
		for(int i = 0;i < keySet.size();i++){
			Object obj = params.get(keySet.get(i));
			ObjectMapper mapper = new ObjectMapper();
			String jsonStr = mapper.writeValueAsString(obj);
			JsonNode jsonNode = mapper.readTree(jsonStr);
			node.set(keySet.get(i), jsonNode);
		}
		return node;
	}
	
	/**
	 * 导入文件接口测试
	 * @param url 接口地址
	 * @param filePath 需要上传的文件
	 * @param paramName 接口接收的参数名，目前只支持一个参数
	 * @return
	 * @throws Exception
	 */
	public static String uploadFile(String url,String filePath,String paramName) throws Exception{
		String loginResponse = HttpConnUtils.login(LOGIN_URL, ACCOUNT, PSW);
		if(loginResponse == null){
			throw new Exception("登录失败！");
		}
		HttpPost httpPost = new HttpPost(url);
        FileBody bin = new FileBody(new File(filePath));
//      StringBody uploadFileName = new StringBody(fileName, ContentType.create("text/plain", Consts.UTF_8));
//      以浏览器兼容模式运行，防止文件名乱码。    
        HttpEntity reqEntity = MultipartEntityBuilder.create().setMode(HttpMultipartMode.BROWSER_COMPATIBLE)  
             .addPart(paramName, bin) //uploadFile对应服务端类的同名属性<File类型>  
//             .addPart("uploadFileName", uploadFileName)//uploadFileName对应服务端类的同名属性<String类型>  
             .setCharset(CharsetUtils.get("UTF-8")).build();  
        httpPost.setEntity(reqEntity);
        HttpResponse response = httpClient.execute(httpPost);
     // 打印响应状态  
        System.out.println("--------------" + response.getStatusLine());  
        // 获取响应对象  
        HttpEntity resEntity = response.getEntity();  
        
		return EntityUtils.toString(resEntity,  
                Charset.forName("UTF-8"));
	}
}
